/**************************************************************************
                       edit.c
This contains the routine to move clones, used by the select Option Menu
and Contig Analysis.
It also contains the Select Option menu and the rest of its routines.

merging contigs (new.c) does NOT use this. Neither does the clone editor.
****************************************************************************/
#include "fpp.h"
#include <gtk/gtkwidget.h>

extern int ZincrFlag;
extern void ConCtgMsg(), ZCtgChrOnly(), initContig(), unbury(), AutoCtgMsg();
extern void contigsAlloc(), ZhighCin(), refreshlist();
extern void displaymarker(), Zsave_selected();
extern int Zredo_selected(), calcmarkerctgpos();
extern int PRTMESS;
extern BOOL movedone;
extern GtkWidget *ctg_window;
extern int called_by_merge;

void snapselected(BOOL right);
static Graph gmove = 0;
void recalccontigs(void);
void setmarkerpos(void);
void move_selected(int from,int result,int distance);
void updateproj(void);
void recalccontigx(int ctg);
void checkmarkercontig(int from,int result);
void settime(struct mytime *mytime);
int movechildren(int ctg,int index,int distance);
void updatemarkerpos(int distance);
void updatemarkerpos2(int distance);

static int cntunbury=0;
/*********************************************************
              DEF: zerorecalc
move all clones from one contig to another
leave counts for markers alone.
**********************************************************/
static void zerorecalc(int from , int to)
{
int i;
CLONE *clone;

  if(contigs[to].count == 0){
     contigs[to].start = contigs[from].start;
     contigs[to].last = contigs[from].last;
     contigs[to].left = contigs[from].left;
     contigs[to].right = contigs[from].right;
     contigs[to].count = contigs[from].count;
     contigs[to].seq = contigs[from].seq;
     contigs[to].ctgdate = contigs[from].ctgdate;
     if (to!=0) {
        contigs[to].ctgQs = contigs[from].ctgQs;
        contigs[to].approxQs = contigs[from].approxQs;
        contigs[to].high_score = contigs[from].high_score;
        contigs[to].avg_score = contigs[from].avg_score;
        contigs[to].low_score = contigs[from].low_score;
        contigs[to].ctgstat = contigs[from].ctgstat;
        strcpy(contigs[to].projmsg, contigs[from].projmsg);

        strcpy(contigs[to].user_msg, contigs[from].user_msg);
        strcpy(contigs[to].chr_msg, contigs[from].chr_msg);
        strcpy(contigs[to].trace_msg, contigs[from].trace_msg);
        contigs[to].chr_pos = contigs[from].chr_pos;
        contigs[to].noedit_pos = contigs[from].noedit_pos;
        contigs[to].noedit_chr = contigs[from].noedit_chr;
     }
  }
  else{
     arrp(acedata,contigs[to].last,CLONE)->next = contigs[from].start;
     contigs[to].last = contigs[from].last;
     contigs[to].count +=contigs[from].count;
     contigs[to].seq += contigs[from].seq;
     settime(&contigs[to].ctgdate);
     if (from!=0 && to!=0) {
        contigs[to].ctgQs = -1;
        contigs[to].approxQs = 0;
        contigs[to].high_score = contigs[to].avg_score = contigs[to].low_score = 0;
        if (contigs[from].ctgstat > contigs[to].ctgstat) 
                   contigs[to].ctgstat=contigs[from].ctgstat;
        ConCtgMsg(to, contigs[from].trace_msg, 1);
        ConCtgMsg(to, contigs[from].user_msg, 2);
        if (contigs[to].noedit_chr==0) contigs[to].chr_msg[0] = '\0';
     }
     if(to != 0){ 
        contigs[to].right = INT_MIN;
        contigs[to].left = INT_MAX;
        for (i=contigs[to].start; i!=-1; i = clone->next) {
            clone = arrp(acedata, i, CLONE);
            contigs[to].left = MiN(contigs[to].left, clone->x);
            contigs[to].right = MaX(contigs[to].right, clone->y);
        }
     }
  } 
  contigs[to].ctg = to;
  initContig(from); 
}

/*************************************************************
                    DEF: move_selected
 fred 4/3/03 -- added called_by_merge flag, as this function
 is now used by the merge contig routine, and we don't want
 to write all the comments, etc.
*************************************************************/
void move_selected(int from,int result,int distance)
{
  CLONE *clone;
  BOOL redrawcurrentclone=FALSE;
  int cin,count;
  char chctg[NAME_SZ],str2[180],str1[180];
  struct markertop *mp;
  struct markerctgpos *mp2;
  MARKER *marker;
  int x, i, flag;

  if (merging && !called_by_merge) {
      printf("Cannot alter contigs while merging.\n");
      return;
  }

  cntunbury=0;
  update=TRUE;
  if (result>=max_contig) contigsAlloc(result);
  if(!called_by_merge){
    if(currentctg != result && contigs[result].count > 0 && 
	       result != from && result != 0 && PRTMESS != 0){
      sprintf(str1,"Contig %d exists with %d clones, add anyway?", 
	     result, contigs[result].count);
      if(!messQuery(str1)){
	  displaymess("No clones moved");
	  return;
      }
    }
  }
  if (from!=result) {
    count=0; /* check if child selected without parent */
    for (cin = contigs[from].start; cin!=-1; cin=clone->next) {
       clone= arrp(acedata,cin,CLONE);
       if(clone->selected!=1) continue;

       if(clone->match[0] != ' '){
         if(!arrp(acedata,clone->parent,CLONE)->selected){
	   printf("Clone %s is buried and parent %s is not selected.\n",
                clone->clone, arrp(acedata,clone->parent,CLONE)->clone);
           ZhighCin(RED,cin);
           count++;
         }
       }
     } 
     if (count > 0) {
        printf(
        "Abort move since %d children selected to move without parent.\n",count);
        return;
     }
  }
                    /* move all selected clones */ 
  count = 0;
  sprintf(chctg,"ctg%d",result);
  for (cin = contigs[from].start; cin!=-1; cin=clone->next) 
  {
      if(cin==clonedisplayed)
          redrawcurrentclone = TRUE;
      clone= arrp(acedata,cin,CLONE);
      if(clone->selected!=1 || clone->selected!=TRUE) continue;
      count++;
      if (count == 1) sprintf(str1,clone->clone);
      
      clone->ctg = result;
      if (PRTMESS==1 || from==0 || result==0) settime(&clone->modified_date);

      if (result==0) {
          clone->x = clone->y = 0;
          if(clone->match[0] != ' ') {
             unbury(cin); /** 19jul00 - request from GSC **/
             cntunbury++;
          }
      }
      else {
         clone->x += distance;
         clone->y += distance;
      }
      strcpy(clone->chctg,chctg);
      if (from!=result && ZincrFlag==0) clone->oldctg = from;
      
      for (mp = clone->marker; mp != NULL; mp = mp->nextmarker)
      {
	  marker = arrp(markerdata,mp->markerindex,MARKER);
          marker->box=0;
          marker->colour=0;
	  for (mp2 = marker->pos; mp2 != NULL; mp2 = mp2->next) {
	    if(mp2->status == AUTO && (mp2->ctg == from || mp2->ctg == result))
	      mp2->status = AUTOUPDATE;
	  }
      }
            /* move them all together with the parents new x & y */
      if (clone->mattype == PARENT || clone->mattype == PSPARENT)
         count += movechildren(from, cin, distance);
  }
        /** Output messages **/
  if (count==0) {
    if (PRTMESS)
      displaymess("No clones Selected, therefore no clones moved");
    return;
  }

  if (PRTMESS && !called_by_merge) {
    if(result != from) {
       if (cntunbury>0) sprintf(str2,
        "Starting with %s... Moved %d clones from ctg%d to ctg%d, unbury %d",
               str1, count,from,result, cntunbury);
       else sprintf(str2,
        "Starting with %s... Moved a total of %d clones from ctg%d to ctg%d",
               str1, count,from,result);
    }
    else
       sprintf(str2,
        "Starting with %s... Moved a total of %d clones a distance of %d",
               str1, count, distance);
    displaymess(str2);
    if(result != from && from!=0) {
      sprintf(str2,"User From Ctg%d.",from);
      AutoCtgMsg(result,str2);
      if (result==0) sprintf(str2,"User Remove %d.", count); 
      else sprintf(str2,"User Split Ctg%d.",result);
      AutoCtgMsg(from,str2);
    }
    else {
      sprintf(str2,"User edit %d.", count);
      AutoCtgMsg(result,str2);
    }
  }
           /** Update contig fields **/
  flag=1;
  if(count == contigs[from].count && from!=result){ /* new contig, move all */
      zerorecalc(from,result);
      if (PRTMESS) {
         printf("Remove Ctg%d\n",from);
         if (result!=0) {
            flag=2;
            currentctg=result;
         }
         else flag=3;
      }
   }
   else  if (from != result) { /* move some */
      settime(&contigs[result].ctgdate);
      settime(&contigs[from].ctgdate);    
              /* just moving a singleton to a contig */
      if (count==1 && from == 0 && contigs[result].count>0) {
           contigs[result].approxQs = 1;
      }
      else {
         contigs[from].ctgQs = contigs[result].ctgQs = -1;
         contigs[from].approxQs = contigs[result].approxQs = 0;
         contigs[from].high_score = contigs[result].high_score = 0;
         contigs[from].avg_score = contigs[result].avg_score = 0;
         contigs[from].low_score = contigs[result].low_score = 0;
      }
      contigs[from].left = contigs[result].left = INT_MAX;
      contigs[from].right = contigs[result].right = INT_MIN;
      contigs[from].count = contigs[from].seq = 0;
      contigs[result].count = contigs[result].seq = 0;

      for(i=0;i<arrayMax(acedata);i++){ 
          clone =  arrp(acedata, i, CLONE);
          if (clone->ctg!=result && clone->ctg!=from) continue;
          if(clone->clone[0] == '!') continue;

          clone->next = -1;
          x = clone->ctg;
          if(contigs[x].count > 0){
             arrp(acedata,contigs[x].last,CLONE)->next = i;
          }
          else{
             contigs[x].start = i;
             contigs[x].ctg = clone->ctg;
          }
          contigs[x].count++;
          contigs[x].last = i;
          contigs[x].left = MiN(contigs[x].left, clone->x);
          contigs[x].right = MaX(contigs[x].right, clone->y);
          
          AddToCtgSeq(clone, x);
      }
      singleton = contigs[0].count;
      if (contigs[from].noedit_chr==0) contigs[from].chr_msg[0] = '\0';
      if (contigs[result].noedit_chr==0) contigs[result].chr_msg[0] = '\0';
   }
   else { /* move clones around in contig */
      contigs[from].left = INT_MAX;
      contigs[from].right = INT_MIN;
      for (cin = contigs[from].start; cin != -1; cin = clone->next) 
      {
           clone = arrp(acedata,cin,CLONE);
	   if(clone->x < contigs[from].left) 
                  contigs[from].left = clone->x;
	   if(clone->y > contigs[from].right) 
                  contigs[from].right = clone->y;
      }
      settime(&contigs[result].ctgdate);
      if (count != contigs[from].count) {
         contigs[from].ctgQs = -1;
         contigs[from].approxQs =  0;
         contigs[from].high_score = 0;
         contigs[from].avg_score =  0;
         contigs[from].low_score =  0;
      }
   }

   if(from == result && currentctg==from) 
        updatemarkerpos2(distance); /* markerstuff */
   else /* assumes new order of clones in contigs struct */
        checkmarkercontig(from,result); 

   if (!PRTMESS) return; /* if called from CBmap/OK,it takes care of the rest */

   if(redrawcurrentclone)
     if(graphActivate(g7))
       displayclone(clonedisplayed);

   if(graphActivate(gmove)) graphDestroy();

   if (from!=result) updateproj();

   if (flag==3) { /* clones moved to 0 */
      if(ctg_window!=NULL) gtk_widget_destroy(ctg_window);
   }
   else if (flag==2) {
      newctg = TRUE; 
      if(!called_by_merge) ctgdisplay(currentctg);
   }
   else {
      movedone=TRUE;
      newctg = TRUE; 
      if(!called_by_merge) ctgdisplay(currentctg);
   }
   refreshlist();
   updateproj();
}
/****************************************************************
                 DEF:  movechildren
****************************************************************/
int movechildren(int oldctg,int index,int distance)
{
  CLONE *clone;
  int cin, count = 0, newctg;
  char chctg[CLONE_SZ+1];
  int x;
  struct markertop *mp;
  struct markerctgpos *mp2;
  MARKER *marker;
  
  clone= arrp(acedata,index,CLONE);
  x = clone->x;
  newctg = clone->ctg;
  sprintf(chctg, "ctg%d", newctg);

  for (cin = contigs[oldctg].start; cin != -1; cin = clone->next)
  {
    clone = arrp(acedata,cin,CLONE);
    if (clone->selected==1) continue;

    if(clone->parent == index){
      count++;
      if (PRTMESS==1 || oldctg==0 || newctg==0) settime(&clone->modified_date);
      clone->ctg = newctg;
      if (oldctg!=newctg && !ZincrFlag) clone->oldctg = oldctg;
      strcpy(clone->chctg, chctg);
         /* FIX: 26mar99 for markers to be moved */
         /* make 2 so don't move again */
      if (oldctg!=newctg) clone->selected=2;

      if (newctg==0) {
          clone->x = clone->y = 0;
          unbury(cin); /** 19jul00 - request from GSC **/
          cntunbury++;
      }
      else if (clone->y == clone->x || oldctg!=newctg) {
          clone->x = x;
          clone->y = x + clone->fp->b2;
      }
      else {
          clone->y += distance;
          clone->x += distance;
      }
      strcpy(clone->chctg,chctg);
            
      for (mp = clone->marker; mp != NULL; mp = mp->nextmarker){
          marker = arrp(markerdata,mp->markerindex,MARKER);
          marker->box=0;
          marker->colour=0;
          for (mp2 = marker->pos; mp2 != NULL; mp2 = mp2->next) {
	    if(mp2->ctg == oldctg || mp2->ctg == newctg) 
              mp2->status = AUTOUPDATE;
          }
      }
    }
  }
  return count;
}
/*********************************************************
             checkmarkercontig
called by move_selected
********************************************************/
void checkmarkercontig(int fromctg,int toctg)
{
  int  cin, keepfromflag;
  int done;
  CLONE *clone;
  MARKER *marker;
  struct markerctgpos *pos,*topos,*frompos;
  char str1[280];
  struct markertop *markertop;
  struct markerclone *markerclone;

  for (cin = contigs[toctg].start; cin!=-1; cin = clone->next) 
  {
    clone = arrp(acedata,cin,CLONE);
    if (clone->selected==0) continue;
    
    clone->selected = FALSE;

    for (markertop = clone->marker; markertop!=NULL;
	markertop =markertop->nextmarker)
    {
        done=1;
        keepfromflag=0;
        topos=frompos=NULL;
	marker = arrp(markerdata,markertop->markerindex,MARKER);

	for (pos = marker->pos; pos!=NULL; pos = pos->next) 
        {
           if (pos->ctg==toctg) topos = pos;
           else if (pos->ctg==fromctg) frompos= pos;
           if (pos->status==AUTOUPDATE) done=0;
        }
        if (fromctg==0 && frompos==NULL) done=0;
        if (done) continue;

        if (frompos!=NULL) {
	   if(arrp(acedata,marker->cloneindex,CLONE)->ctg == fromctg)
	     keepfromflag = 1;
	   for (markerclone = marker->nextclone; !keepfromflag && markerclone != NULL;
	       markerclone = markerclone->nextclone)
           {
	     if(arrp(acedata,markerclone->cloneindex,CLONE)->ctg == fromctg)
	       keepfromflag = 1;
	   }
        }

        if (topos==NULL && toctg != 0 && (frompos==NULL || keepfromflag==1)) { /* create */
            sprintf(str1,"Add marker %s to ctg%d",marker->marker, toctg);
            if (PRTMESS) displaymess(str1);
            contigs[toctg].markers++;
	    topos = (struct markerctgpos *) 
	      messalloc((sizeof(struct markerctgpos)));
	    if(marker->pos == NULL) marker->pos = topos; 
            else {
	      for (pos=marker->pos; pos->next !=NULL;  pos=pos->next);
              pos->next = topos;
            }
            topos->next=NULL;
         }
         else if ((topos!=NULL || toctg==0) && frompos!=NULL && keepfromflag==0) { /* delete */
            if(!called_by_merge){  /*fred 4/3/03*/
              sprintf(str1,"Remove marker %s from ctg%d",marker->marker, frompos->ctg);
              if (PRTMESS) displaymess(str1);
            }
            contigs[fromctg].markers--;
            if (marker->pos->ctg == fromctg) {
                frompos = marker->pos;
                marker->pos = frompos->next;
            }
            else {
	        for(pos = marker->pos; pos->next->ctg != fromctg; pos =pos->next);
                frompos = pos->next;
	        pos->next= pos->next->next;
            }
            messfree(frompos);
            frompos=NULL;
         }
	 else if (topos==NULL && (frompos!=NULL && keepfromflag==0)){ /* replace */
            if(!called_by_merge){  /*fred 4/3/03*/
              sprintf(str1,"Remove marker %s from ctg%d, add to ctg%d",
                            marker->marker,fromctg,toctg);
              if (PRTMESS) displaymess(str1);
            }
            contigs[toctg].markers++;
            contigs[fromctg].markers--;
	    topos = frompos;
            frompos=NULL;
	 }
         if (frompos) {
	    frompos->status = AUTO;
	    frompos->ctg = fromctg;
	    frompos->pos = calcmarkerctgpos(frompos,markertop->markerindex);
         }
         if (topos) {
	    topos->status = AUTO;
	    topos->ctg = toctg;
	    topos->pos = calcmarkerctgpos(topos,markertop->markerindex);
         }
         if (markerdisplayed==markertop->markerindex && graphExists(gmarker)) {
             displaymarker(markerdisplayed);
         }
         if (PRTMESS==1 || fromctg==0 || toctg==0) 
                 settime(&marker->modified_date);
      }
   }
   if (contigs[fromctg].count==0) contigs[fromctg].markers = 0;
}
/**********************************************************
CAS - 5 oct 97
**********************************************************/
void flipselected()
{
struct contig *p;
int i, rt, lt;
CLONE *clp;

  if(ctg_window==NULL)
    return; 

  if(merging){
    displaymess("Not available while merging");
    return;
  }
  for (lt=99999, rt=-99999, p = root; p != NULL; p = p->new) {
       clp = arrp(acedata,p->next,CLONE); 
       if (clp->selected)  {
           rt = MaX(rt, clp->y);
           lt = MiN(lt, clp->x);
       }
  }
  for (p = root; p != NULL; p = p->new) {
       clp = arrp(acedata,p->next,CLONE); 
       if (clp->selected) {
           i = clp->x;
           clp->x = (- clp->y + rt) + lt; 
           clp->y = (- i + rt) + lt;
       } 
  }
  Zsave_selected(1);
  move_selected(currentctg,currentctg,0);
  Zredo_selected();
}
/************************************************************
                   DEF: snapselected
**************************************************************/
void snapselectedleft()
{
  snapselected(FALSE);
}

void snapselectedright()
{
  snapselected(TRUE);
}

void snapselected(BOOL right)
{
  struct contig *pctg;
  BOOL last = FALSE,first=TRUE;
  CLONE *clone;
  int newoffset,left=-1;

  if(ctg_window==NULL)
    return; 

  if(merging){
    displaymess("Not available while merging");
    return;
  }
  if(!barhighlighted){
     displaymess("Select a bar to snap to");
     return;
  }

  update= TRUE;
  if(!right){
      pctg = root;
      while(!last){
	clone= arrp(acedata,pctg->next,CLONE);
	if(clone->selected){
	  if(first){
	    left = clone->x;
	    first = FALSE;
	  }
	  else if(clone->x < left)
	    left= clone->x;
	}
	if(pctg->new==NULL) /* if theres another go again else set flag to stop  */
	  last = TRUE;	
	else
	  pctg = pctg->new;
      }
   }
   else{
      pctg = root;
      while(!last){
	clone= arrp(acedata,pctg->next,CLONE);
	if(clone->selected){
	  if(first){
	    left = clone->y;
	    first = FALSE;
	  }
	  else if(clone->y > left)
	    left= clone->y;
	}
	if(pctg->new==NULL) /* if theres another go again else set flag to stop  */
	  last = TRUE;	
	else
	  pctg = pctg->new;
      }
   }
   if(!first){
      newoffset = region[bar_active].band - left;
      Zsave_selected(1);
      move_selected(currentctg,currentctg,newoffset);
      Zredo_selected();
      ctgdisplay(currentctg);
   }
   else
      displaymess("No Clones are selected");
}

/********************************************************
              DEF: checkreqctg
*********************************************************/
static int checkreqctg()
{
  int result;
  char str1[180];
  struct contig *pctg;
  CLONE *clone;
  int minimum = INT_MAX;
  int i, n;

  if(reqctg[0]=='n'){
    for (n=-1, i=1; i<=max_contig; i++) 
       if (contigs[i].count==0) {
           n = i;
           break;
       }
    if (n== -1) n = max_contig+1;
    sprintf(reqctg,"%d",n);
  }
  else if(reqctg[0]==' ' || reqctg[0]=='\0' || reqctg[0]=='\n' || !sscanf(reqctg,"%d",&result))
  {
    sprintf(str1,"Must be an Integer. Input %s is rejected.",reqctg);
    displaymess(str1);
    return minimum;
  }

  for (pctg = root; pctg!=NULL; pctg = pctg->new) {
      clone= arrp(acedata,pctg->next,CLONE);
      if(clone->selected)
          if(clone->x < minimum) minimum = clone->x;
  }  
  return minimum;
}

static void requestctg(char *temp)
{
  int result2;

  result2 = checkreqctg();
}

/********************************************************************
                  DEF: selectedmove
Moves selected set to another contig
*******************************************************************************/
void newcontigbit()
{
  int minimum,result;

  minimum = checkreqctg();
  if(minimum != INT_MAX)
    if(sscanf(reqctg,"%d",&result))
      move_selected(currentctg,result,(contigs[result].left-minimum));
}

/********************************************************************
                  DEF: selectedmove
Edit Contig - Move/Remove operation. Menu to moves selected set to another contig
*******************************************************************/
void selectedmove()
{
  struct contig *pctg;
  BOOL found = FALSE;
  int i;
  int n;
  char str1[80];

  if(ctg_window==NULL)
    return;
  if(merging){
    displaymess("Not available while merging");
    return;
  }
  pctg = root;
  while(pctg != NULL && !found){
    if(arrp(acedata,pctg->next,CLONE)->selected)
      found = TRUE;
    pctg = pctg->new;
  }
  if(found){
    if(graphActivate(gmove)){ 
      graphClear();
      graphPop();
    }
    else{ 
      gmove = graphCreate (TEXT_FIT,"Move selected",.2,.2,.4,.15) ;
    }
    for (n=-1, i=1; i<=max_contig; i++) 
       if (contigs[i].count==0) {
           n = i;
           break;
       }
    if (n== -1) n = max_contig+1;
    sprintf(str1, "Next Ctg# %d  Highest Ctg# %d",n, getcontigsmax());
    graphText(str1,2.0,2.0);
    graphText("Move selected to contig",2.0,4.0);
    reqctg[0]= '\0';
    graphTextEntry(reqctg, 5, 27.0, 4.0,requestctg);
    
    graphButton("Reject",graphDestroy,17.0,6.0);
    graphButton("Accept",newcontigbit,6.0,6.0);
    graphText("Enter 0 to remove",2.0,8.0);
    graphRedraw();
  }
  else{
    displaymess("No Clones Selected");
  }
}

/*************************************************************
               DEF: snaphighlight
***********************************************************/
void snaphighlighted(BOOL right)
{
int cloneoffset;
CLONE *clone;

  if(ctg_window==NULL)
    return; 
  if (clhigh==NULL) {
     displaymess("No highlighted clone");
     return;
  }
  if (!barhighlighted) {
     displaymess("Select a bar to snap to");
     return;
  }
  if (merging) {
     displaymess("Finish merge before snapping");
     return;
  }
  clone = arrp(acedata, clhigh->next, CLONE);
  if (clone->ctg != currentctg) {
     displaymess("Highlighted clone not in current contig");
     return;
  }
  if(!right)
    cloneoffset = region[bar_active].band - clone->x;
  else
    cloneoffset = region[bar_active].band - clone->y;

  Zsave_selected(0);
  clone->selected = 1;
  move_selected(currentctg, currentctg, cloneoffset);
  clone->selected = 0;
  if (Zredo_selected()) ctgdisplay(currentctg);
}

void snaphighright()
{
  snaphighlighted(TRUE);
}

void snaphighleft()
{
  snaphighlighted(FALSE);
}

/****************************************************************
               DEF: resizehigh
Stretch highlighted clone.
****************************************************************/
void resizehigh(BOOL right)
{
  CLONE *clone;
  int tmp;
  char str[30];

  if(ctg_window==NULL)
    return; 
  if(merging){
    displaymess("Not available while merging");
    return;
  }
  if (!barhighlighted) {
     sprintf(str,"Select a bar to stretch to");
     displaymess(str);
     return;
  }
  if (merging) {
     sprintf(str,"Finish merge before stretching");
     displaymess(str);
     return;
  }
  if(clhigh != NULL && !merging){
    update= TRUE;
    clone= arrp(acedata,clhigh->next,CLONE);
    if(barhighlighted){
      if(!right)
	clone->x =  region[bar_active].band;
      else
	clone->y = region[bar_active].band;
      if(clone->x > clone->y){
	tmp = clone->x;
	clone->x = clone->y;
	clone->y = tmp;
      }
      recalccontigx(currentctg);
      ctgdisplay(currentctg);
    }
  } 
}

void resizehighleft(void)
{
  resizehigh(FALSE);
}
void resizehighright(void)
{
  resizehigh(TRUE);
}
